package com.lzh.runke.core.web_base.enums.deserializer;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Lists;
import com.lzh.runke.core.web_base.enums.BaseEnum;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 枚举(多个)反序列化器
 *
 * @author xie
 */
public class EnumMultiDeserializer extends JsonDeserializer<Collection<BaseEnum>> {

    @Override
    @SuppressWarnings("unchecked")
    public Collection<BaseEnum> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);

        //实体类
        Object currentValue = jp.getCurrentValue();

        //实体类中枚举属性名
        String currentName = jp.currentName();

        // 通过反射拿到所有字段
        List<Field> fields = Lists.newArrayList(currentValue.getClass().getDeclaredFields());
        // 拿到字段匹配的 Field
        List<Field> matchedFields = fields.parallelStream().filter(item -> item.getName().equals(currentName)).collect(Collectors.toList());
        if (!matchedFields.stream().findFirst().isPresent()) {
            throw new RuntimeException("未找到匹配字段");
        }
        Field field = matchedFields.stream().findFirst().get();
        // 获取数组对应的泛型的 Class
        ParameterizedType pt = (ParameterizedType) field.getGenericType();
        Class clazz = (Class) pt.getActualTypeArguments()[0];

        JsonFormat annotation = (JsonFormat) clazz.getAnnotation(JsonFormat.class);
        //枚举
        List<BaseEnum> ems = Lists.newArrayListWithExpectedSize(node.size());
        if (annotation == null || annotation.shape() != JsonFormat.Shape.OBJECT) {
            for (JsonNode item : node) {
                ems.add((BaseEnum) Enum.valueOf(clazz, item.get("value").asText()));
            }
        } else {
            List<BaseEnum> enums = Arrays.asList((BaseEnum[]) clazz.getEnumConstants());

            for (JsonNode item : node) {
                List<BaseEnum> matched;
                matched = enums.parallelStream().filter(e -> item.get("value").asText().equals(e.getValue().toString())).collect(Collectors.toList());

                if (matched.stream().findFirst().isPresent()) {
                    ems.add(matched.stream().findFirst().get());
                } else {
                    throw new RuntimeException(item.asText() + "未匹配上对应的枚举");
                }
            }
        }
        return ems;
    }
}
